package edu.vt.ece.util;

import java.util.concurrent.locks.ReentrantLock;

/**
 * User: Jeremy Tate and Brian Cheng
 * This is the node class that is used by the AVL tree
 */
public class Node {
	private int key; // the value of the node, which is used to determine

	// position in the tree
	private Node left;
	private Node right;
	private Node parent;

	public ReentrantLock lock;

	public Node(int item) {
		key = item;
		left = null;
		right = null;
		parent = null;
		lock = new ReentrantLock();
	}

	public int getKey() {
		return key;
	}
	
	public void setKey(int key) {
		this.key = key;
	}
	
	public Node getLeft() {
		return left;
	}

	public void setLeft(Node left) {
		this.left = left;
	}

	public Node getRight() {
		return right;
	}

	public void setRight(Node right) {
		this.right = right;
	}

	public Node getParent() {
		return parent;
	}

	public void setParent(Node parent) {
		this.parent = parent;
	}

	public boolean getLock()
	{
		if(!lock.tryLock()) return false;
		return true;
	}

	public void releaseLock()
	{
		while(lock.isHeldByCurrentThread()) {
			lock.unlock();
		}
	}

	/**
	 * This finds the height of the left subtree from this node
	 * 
	 * @return
	 */
	public int getLeftHeight() {
		int height = 1;
		// get the maximal height of both children of this node
		if (left != null) {
			height += Math.max(left.getLeftHeight(), left.getRightHeight());
		} else {
			return 0;
		}
		return height;
	}

	/**
	 * This finds the height of the right subtree from this node
	 * 
	 * @return
	 */
	public int getRightHeight() {
		int height = 1;
		// get the maximal height of both children of this node
		if (right != null) {
			height += Math.max(right.getLeftHeight(), right.getRightHeight());
		} else {
			return 0;
		}
		return height;
	}

	/**
	 * Returns the balance factor of the node. Balance factor is defined as the
	 * height of the left subtree - height of the right subtree
	 * 
	 * @return
	 */
	public int getBalanceFactor() {
		return getLeftHeight() - getRightHeight();
	}

	/**
	 * This finds the height of the subtree from this node
	 * 
	 * @return
	 */
	public int getHeight() {
		int rightHeight = 1;
		int leftHeight = 1;

		// get the maximal height of both children of this node
		if (right != null) {
			rightHeight += Math.max(right.getLeftHeight(),
					right.getRightHeight());
		} else {
			rightHeight = 0;
		}

		// get the maximal height of both children of this node
		if (left != null) {
			leftHeight += Math.max(left.getLeftHeight(), left.getRightHeight());
		} else {
			leftHeight = 0;
		}

		return Math.max(leftHeight, rightHeight);

	}

	public String toString()
	{
		StringBuffer sb = new StringBuffer("key: ").append(key);
		if (left != null)
		{
			sb.append("\n").append("left: ").append(left.getKey());
		}
		if (right != null)
		{
			sb.append("\n").append("right: ").append(right.getKey());
		}
		if (parent != null)
		{
			sb.append("\n").append("parent: ").append(parent.getKey());
		}
		return sb.toString();
	}
}
